package com.jhw.ymcc.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.jhw.doc.CourseDoc;
import com.jhw.ymcc.constants.MqConstants;
import com.jhw.ymcc.domain.*;
import com.jhw.ymcc.dto.CourseAddDto;
import com.jhw.ymcc.dto.MessageSmsDto;
import com.jhw.ymcc.dto.UserSmsDto;
import com.jhw.ymcc.exception.GlobalErrorCode;
import com.jhw.ymcc.feign.MediaFileService;
import com.jhw.ymcc.feign.SearchService;
import com.jhw.ymcc.mapper.CourseMapper;
import com.jhw.ymcc.mapper.CourseTypeMapper;
import com.jhw.ymcc.result.JSONResult;
import com.jhw.ymcc.service.*;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.jhw.ymcc.util.AssertUtil;
import com.jhw.ymcc.vo.CourseDetailVo;
import com.jhw.ymcc.vo.CourseInfoVo;
import com.jhw.ymcc.vo.CourseOrderVo;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author jhw
 * @since 2022-10-03
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {

    @Autowired
    private ITeacherService teacherService;

    @Autowired
    private ICourseDetailService courseDetailService;

    @Autowired
    private ICourseMarketService courseMarketService;

    @Autowired
    private ICourseResourceService courseResourceService;

    @Autowired
    private ICourseSummaryService courseSummaryService;

    @Autowired
    private CourseMapper courseMapper;

    @Autowired
    private CourseTypeMapper courseTypeMapper;

    @Autowired
    private ICourseTypeService courseTypeService;

    @Autowired
    private SearchService searchService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private ICourseChapterService courseChapterService;

    @Autowired
    private MediaFileService mediaService;

    /**
     * 课程详情
     * @param courseId
     * @return
     */
    @Override
    public CourseDetailVo detail(Long courseId) {
        // 参数校验
        Course course = selectById(courseId);
        AssertUtil.isNotNull(course, GlobalErrorCode.COURSE_DOESNOTEXIST_ERROR);
        boolean bb = Course.STATUS_ON_LINE == course.getStatus();
        AssertUtil.isTrue(bb, GlobalErrorCode.COURSE_NOT_ON);
        // 查询相关数据并进行封装
        CourseSummary courseSummary = courseSummaryService.selectById(courseId);
        CourseMarket courseMarket = courseMarketService.selectById(courseId);
        CourseDetail courseDetail = courseDetailService.selectById(courseId);
        // 通过课程id查询teacher
        List<Teacher> teachers = courseMapper.selectTeachersByCourseId(courseId);
        // 获取课程下的所有章节
        Wrapper<CourseChapter> wrapper = new EntityWrapper<>();
        wrapper.eq("course_id", courseId);
        List<CourseChapter> courseChapters = courseChapterService.selectList(wrapper);
        // 收集数据到map集合中
        Map<Long, CourseChapter> collect = courseChapters.stream().collect(Collectors.toMap(CourseChapter::getId, courseChapter -> courseChapter));
        // 通过feign调用媒体服务，获取到json结果
        JSONResult jsonResult = mediaService.getMediaFileByCourseId(courseId);
        // 断言是否调用成功
        AssertUtil.isTrue(jsonResult.isSuccess(), GlobalErrorCode.ERROR);
        // 获取到结果中的数据
        Object data = jsonResult.getData();
        AssertUtil.isNotNull(data, GlobalErrorCode.ERROR);
        // 参照MediaFile这个类将data数据转成一个个实体类
        List<MediaFile> mediaFiles = JSON.parseArray(data.toString(), MediaFile.class);
        mediaFiles.forEach(e ->{
            e.setFileUrl("");
            CourseChapter courseChapter = collect.get(e.getChapterId());
            if (courseChapter != null){
                courseChapter.getMediaFiles().add(e);
            }
        });
        return new CourseDetailVo(course, courseMarket, courseChapters, teachers, courseDetail, courseSummary);
    }

    @Override
    public CourseInfoVo courseOrderInfo(String courseIds) {
        // 判断courseId是否违法
        Set<Long> collect = Arrays.stream(courseIds.split(","))
                // 过滤空字符串
                .filter(id -> !StringUtils.isEmpty(id))
                // 转华化lang
                .map(id -> Long.valueOf(id))
                // 用set集合收集
                .collect(Collectors.toSet());
        // 判断你的长度和我过滤后的长度要一致，否则就是有问题，就抛一个异常
        boolean boo = collect.size() == courseIds.split(",").length;
        AssertUtil.isTrue(boo, GlobalErrorCode.ERROR);
        // 查询所有课程
        List<Long> courseIdslist = collect.stream().collect(Collectors.toList());
        List<Course> courses = selectBatchIds(courseIdslist);
        AssertUtil.isNotNull(courses, GlobalErrorCode.ERROR);

        Map<Long, CourseMarket> courseMarketMap  = courseMarketService.selectBatchIds(courseIdslist).stream().collect(Collectors.toMap(CourseMarket::getId, courseMarket -> courseMarket));
        CourseInfoVo courseInfoVo = new CourseInfoVo();
        ArrayList<CourseOrderVo> list = new ArrayList<>();

        // 遍历所有课程封装返回值
        courses.forEach(course ->{
            CourseOrderVo courseOrderVo = new CourseOrderVo();
            boolean bo = Course.STATUS_ON_LINE == course.getStatus();
            AssertUtil.isTrue(bo, GlobalErrorCode.ERROR);
            CourseMarket courseMarket = courseMarketMap.get(course.getId());
            AssertUtil.isNotNull(courseMarket, GlobalErrorCode.ERROR);
            courseOrderVo.setCourse(course);
            courseOrderVo.setCourseMarket(courseMarket);
            courseInfoVo.setTotalAmount(courseInfoVo.getTotalAmount().add(courseMarket.getPrice()));
            list.add(courseOrderVo);
        });
        courseInfoVo.setCourseInfoVos(list);
        return courseInfoVo;
    }


    /**
     * 课程上架
     * @param courseId
     */
    @Override
    @Transactional
    public void onLineCourse(Long courseId) {
        // 根据id查询课程
        Course course = selectById(courseId);
        // 断言，为空就抛异常
        AssertUtil.isNotNull(course, GlobalErrorCode.COURSE_DOESNOTEXIST_ERROR);
        // 修改课程状态
        course.setStatus(Course.STATUS_ON_LINE);
        course.setOnlineTime(new Date());
        updateById(course);
        // 设置CourseDoc数据
        // 查询数据
        CourseType courseType = courseTypeService.selectById(course.getCourseTypeId());
        CourseMarket courseMarket = courseMarketService.selectById(course.getId());
        CourseSummary courseSummary = courseSummaryService.selectById(course.getId());
        // 拷贝数据到doc对象中
        CourseDoc courseDoc = new CourseDoc();
        BeanUtils.copyProperties(course, courseDoc);
        BeanUtils.copyProperties(courseMarket, courseDoc);
        BeanUtils.copyProperties(courseSummary, courseDoc);
        courseDoc.setCourseTypeName(courseType.getName());
        String Charge = courseMarket.getCharge() == 1 ? "免费" : "收费";
        courseDoc.setCharge(Charge);
        // 调用seach服务，将数据保存到ES
        JSONResult jsonResult = searchService.saveCourseEs(courseDoc);
        // 断言如果发布失败就抛出异常
        AssertUtil.isTrue(jsonResult.isSuccess(), GlobalErrorCode.COURSE_RELEASE_ERROR);
        sendMessage(courseDoc);

    }

    /**
     * 课程下架
     * @param courseId
     */
    @Override
    public void offLineCourse(Long courseId) {
        // 根据id查询课程
        Course course = selectById(courseId);
        // 断言，为空就抛异常
        AssertUtil.isNotNull(course, GlobalErrorCode.COURSE_DOESNOTEXIST_ERROR);
        // 修改课程状态为下架
        course.setStatus(Course.STATUS_OFF_LINE);
        course.setEndTime(new Date());
        updateById(course);
        CourseDoc courseDoc = new CourseDoc();
        // 设置要删除课程的id
        courseDoc.setId(courseId);
        // 调用search服务删除es中的课程
        JSONResult jsonResult = searchService.delCourseEs(courseDoc);
        // 如果删除失败就抛出异常
        AssertUtil.isTrue(jsonResult.isSuccess(), GlobalErrorCode.COURSE_REMOVE_ERROR);

    }



    private void sendMessage(CourseDoc courseDoc) {
        MessageSmsDto messageSmsDto = new MessageSmsDto();
        messageSmsDto.setTitle("课程发布啦！！！");
        messageSmsDto.setContent("亲爱的用户您好，最新课程 <a href='localhost:6002/list.html?courseId=\"+courseDoc.getId()+\"'> 测试 </a> 发布啦，点击课程了解详情");
        // 需要发送短信的用户（写死）
        List<UserSmsDto> userSmsDtos = Arrays.asList(new UserSmsDto(1L, "18011234064"),
                new UserSmsDto(1L, "18090928627"));
        messageSmsDto.setUsers(userSmsDtos);
        rocketMQTemplate.sendOneWay( MqConstants.COURSE_SMS_TOPIC+ ":" + MqConstants.COURSE_SMS_TAG
                , JSON.toJSONString(messageSmsDto));
    }

    @Override
    @Transactional
    public void save(CourseAddDto courseAddDto) {
        Course course = courseAddDto.getCourse();
        CourseDetail courseDetail = courseAddDto.getCourseDetail();
        CourseMarket courseMarket = courseAddDto.getCourseMarket();
        CourseResource courseResource = courseAddDto.getCourseResource();
        List<Long> teacharIds = courseAddDto.getTeacharIds();
        // 校验课程名字，名字重复不可以添加
        Course courseTmp = selectByName(course.getName());
        AssertUtil.isNull(courseTmp, GlobalErrorCode.COURSE_EXISTS_ERROR);
        // 新增课程
        Long CourseId = savaCourse(course, teacharIds);
        // 新增课程详情
        courseDetail.setId(CourseId);
        saveCourseDetail(courseDetail);
        // 新增课程销售表
        courseMarket.setId(CourseId);
        saveCourseMarket(courseMarket);
        // 新增课程资源
        courseResource.setCourseId(CourseId);
        savaCourseResource(courseResource);
        // 初始化课程统计
        initCourseSummary(CourseId);
        // 新增课程讲师
        courseMapper.insertCourseTeacher(CourseId, teacharIds);
        // 对应类型课程数量加一
        courseTypeMapper.updateTotalCountById(course.getCourseTypeId());
    }



    private void initCourseSummary(Long courseId) {
        // 初始化消息对象
        CourseSummary courseSummary = new CourseSummary();
        courseSummary.setId(courseId);
        courseSummaryService.insert(courseSummary);

    }

    private void savaCourseResource(CourseResource courseResource) {
        courseResourceService.insert(courseResource);
    }

    private void saveCourseMarket(CourseMarket courseMarket) {
        courseMarketService.insert(courseMarket);
    }

    private void saveCourseDetail(CourseDetail courseDetail) {
        courseDetailService.insert(courseDetail);
    }

    private Long savaCourse(Course course, List<Long> teacharIds) {
        // 设置默认状态为下线
        course.setStatus(course.STATUS_OFF_LINE);
        // 用户写死
        course.setLoginId(3L);
        //
        course.setLoginUserName("13330964748");
        String TeacherNames = teacherService.selectBatchIds(teacharIds).stream().
                map(teacher -> teacher.getName()).collect(Collectors.joining(","));
        course.setTeacherNames(TeacherNames);
        insert(course);
        return course.getId();
    }

    private Course selectByName(String name) {
        Wrapper<Course> wrapper = new EntityWrapper<>();
        wrapper.eq("name", name);
        return selectOne(wrapper);
    }
}
